ZF.add('base', function(Z) {
    
    var E = Z.Env,

        win = E.win,

        doc = E.doc,

        // Dom already ?
        isReady,

        // Has the ready events already been bound?
        readyBound,
        
        // The functions to execute on DOM ready.
        readyFns = [];


    Z.extend({

        isReady : function() {
            return !!isReady;
        },

        ready : function(fn) {
            if (!readyBound) _bindReady();

            // If the DOM is already ready
            if (isReady) {
                // Execute the function immediately
                fn.call(E.win, this);
            } else {
                // Remember the function for later
                readyFns.push(fn);
            }

            return this;
        }
    });

    // call once to fix 
    // domready listener added too late  in  !IE browser
    Z.ready(Z.emptyFn);


    function _onReady(isLoad) {
        if (isReady) return;

        isReady = true;
        
        if (readyFns) {
            var fn, i = 0;
            while (fn = readyFns[i++]) {
                fn.call(E.win, Z);
            }

            readyFns = null;
        }
    }

    function _bindReady() {

        readyBound = true;

        // Catch cases where ZF.ready() is called after the
		// browser event has already occurred.
        if (/loaded|complete/.test(doc.readyState)) {
            // Handle it asynchronously to allow scripts the opportunity to delay ready
            return setTimeout(_onReady, 1);
        }

        var doScroll = doc.documentElement.doScroll,
            eType = doScroll ? 'onreadystatechange' : 'DOMContentLoaded';

        if (doc.addEventListener) { // W3C : Mozilla, Opera and webkit nightlies currently support this event
            doc.addEventListener(eType, function() {
                doc.removeEventListener(eType, arguments.callee, false);
                _onReady();
            }, false);

            win.addEventListener('load', function() {
                doc.removeEventListener('load', arguments.callee, false);
                _onReady(true);
            }, false);
        
        } else { // If IE event model is used
            // ensure firing before onload, maybe late but safe also for iframes
            doc.attachEvent(eType, function() {
                if (/loaded|complete/.test(doc.readyState)) {
                    doc.detachEvent(eType, arguments.callee);
                    _onReady();
                }
            });

            // A fallback to window.onload, that will always work.
            win.attachEvent('onload', function() {
                doc.detachEvent('onload', arguments.callee);
                _onReady(true);
            });

            // If IE and not a frame
            // continually check to see if the document is ready
            var notframe = false;

            try {
                notframe = win['frameElement'] == null;
            } catch(e) {
            }

            if (doScroll && notframe) {
                (function() {
                    try {
                        // Ref: http://javascript.nwbox.com/IEContentLoaded/
                        doScroll('left');
                        _onReady();
                    } catch(ex) {
                        setTimeout(arguments.callee, 10);
                    }
                })();
            }
        }
    }

});
